package controller;

import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;

import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import model.Level;
import model.StateSupport;
import model.memento.MementoManager;
import resources.GlobalSettings;
import view.LevelDisplayView;

public class SokobanController extends JPanel implements
		PropertyChangeListener, ChangeListener {

	private static final long serialVersionUID = -528738078741265590L;

	/**
	 * Nivel
	 */
	private Level level;
	
	/**
	 * memento manager de los menus undo y redo
	 */
	private MementoManager mementoManager;

	/**
	 * End level event listener
	 */
	private StateSupport endLevelEventListeners;

	public SokobanController() {
		super(new BorderLayout());
		this.setBackground(GlobalSettings.panelColor);
		this.setOpaque(true);
		this.setFocusable(false);

		this.mementoManager = new MementoManager();
		this.endLevelEventListeners = new StateSupport();
	}

	/**
	 * Reset level a partir del nuevo file.
	 * 
	 * @param file
	 */
	public void reset(URL file) {
		this.removeAll();

		loadLevel(file);
		setLevelView();

		this.validate();
		this.repaint();
	}

	/**
	 * Cargar file en level.
	 * 
	 * @param path
	 */
	public void loadLevel(URL path) {
		this.level = new Level(path);
	}

	private void setLevelView() {
		LevelDisplayView levelView = new LevelDisplayView(this.level);
		levelView.setFocusable(true);
		levelView.addKeyListener(new ManPieceController(level.getMan()));
		this.add(levelView, BorderLayout.CENTER);
		levelView.requestFocusInWindow();
	}

	/**
	 * @return Memento level
	 */
	public MementoManager getLevelMemento() {
		return this.mementoManager;
	}

	/**
	 * Evento FileLevel ha cambiado.
	 * 
	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
	 */
	@Override
	public void propertyChange(PropertyChangeEvent arg0) {
		// borrar listener de mementoSupport
		if (this.level != null) {
			this.level.removeMementoSupportEventListener(mementoManager);
		}
		// reset level con nuevo file
		reset((URL) arg0.getNewValue());
		// agregar listener de mementoSupport
		this.level.addMementoSupportEventListener(mementoManager);
		this.mementoManager.discardAllEdits();
		// agregar listener de endLevel event
		this.level.addEndLevelEventListener(this);
	}

	/**
	 * Agregar un listener a la lista de evento EndLevel.
	 * 
	 * @param listener
	 */
	public void addEndLevelEventListener(ChangeListener listener) {
		this.endLevelEventListeners.addStateChangeListener(listener);
	}

	/**
	 * Borrar un listener de la lista de evento EndLevel.
	 * 
	 * @param listener
	 */
	public void removeEndLevelEventListener(ChangeListener listener) {
		this.endLevelEventListeners.removeStateChangeListener(listener);
	}

	/**
	 * Recibir el evento EndLevel desde Level y pasarlos a los listeners
	 * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
	 */
	@Override
	public void stateChanged(ChangeEvent arg0) {
		endLevelEventListeners.fireStateChangedEvent();
	}
}
